﻿using System.Collections.Generic;
using System.Globalization;
using System.Windows;
using System.Windows.Media;
using TextEditor.TextBoxInner.Utils;

namespace TextEditor.TextBoxInner.DrawingElements
{
	internal class NumberLine : DrawingVisual
	{
		private static readonly Brush DefaultFontBrush = Brushes.Black;

		private readonly List<ushort> _glyphIndexes = new List<ushort>(100);
		private readonly List<double> _advanceWidths = new List<double>(100);

		private int? _number;

		public NumberLine()
		{
			VisualTextRenderingMode = TextRenderingMode.ClearType;
		}

		public bool IsVisible
		{
			get { return _number.HasValue; }
		}

		public int LineIndex
		{
			get { return _number.Value; }
		}

		public void SetTop(double topOffset)
		{
			VisualOffset = new Vector(0, topOffset);
		}

		public void SetContent(int? number)
		{
			if (_number == number)
				return;

			_number = number;
			Draw();
		}

		private void Draw()
		{
			DrawingContext drawing = RenderOpen();

			try
			{
				if (_number.HasValue)
					DrawText(drawing, (_number.Value + 1).ToString(CultureInfo.InvariantCulture), DefaultFontBrush);
			}
			finally
			{
				drawing.Close();
			}
		}

		public override string ToString()
		{
			return IsVisible ? "Line: " + LineIndex : "Invisible";
		}
		
		private void DrawText(DrawingContext drawingContext, string text, Brush brush)
		{
			if (string.IsNullOrEmpty(text))
				return;

			_glyphIndexes.Clear();
			_advanceWidths.Clear();

			for (int n = 0, max = text.Length; n < max; n++)
			{
				char ch = text[n];

				ushort glyphIndex;
				if (!FontHelper.GlyphTypeface.CharacterToGlyphMap.TryGetValue(ch, out glyphIndex))
					glyphIndex = FontHelper.GlyphUnknownIndex;

				_glyphIndexes.Add(glyphIndex);
				_advanceWidths.Add(FontHelper.FontWidth);
			}

			GlyphRun glyphRun = new GlyphRun(FontHelper.GlyphTypeface, 0, false, FontHelper.FontSize,
				_glyphIndexes.ToArray(), new Point(0, FontHelper.FontSize), _advanceWidths.ToArray(), null, null, null, null, null, null);

			drawingContext.DrawGlyphRun(brush, glyphRun);
		}
	}
}
